import { apiAccount as api } from '@/services';
import Base64 from 'base-64';
import { makeObservable, observable, toJS } from 'mobx';

/**
 * 将auth接口返回的tokenModel解析
 * @param {
 *   tokenModel: object,    // 原始model
 *   username: string,      // 用户名
 *   payload: object,       // token中携带的数据
 * } tokenModel
 */
function parseToken(tokenModel) {
  const payloadEnc = tokenModel?.token.split('.')[1];
  const payload = JSON.parse(Base64.decode(payloadEnc.replace(/-/g, '+').replace(/_/g, '/')));
  const username = payload?.sub;
  // eslint-disable-next-line no-param-reassign
  tokenModel.expires = payload?.exp - payload?.iat;
  return { tokenModel, payload, username };
}

export default class LoginStore {
  _tokenModel = { token: false, expires: 0 };
  endpoints = {};
  lastUsername = '';
  tokenPayload = null;
  me = {};
  _VP = null;

  constructor(rootStore) {
    makeObservable(this, {
      me: observable,
      _VP: observable,
    });
    this.rootStore = rootStore;
    try {
      this._load();
      setInterval(this._refreshTokenIfNeeded, 1800 * 1000);
    } catch (e) {
      console.warn(`Failed load token from localStorage: ${e}`);
    }
    Events.on(EVENT.TOKEN_FAILED, () => {
      if (TOKEN) {
        this.logout().then(() => setTimeout(() => window.location.reload(), 0));
      }
    });
  }

  _refreshTokenIfNeeded = () => {
    if (!this._tokenModel?.token) return;
    const currentTimestamp = new Date().getTime() / 1000;
    const elapsedSeconds = (currentTimestamp - this.tokenPayload.iat);
    if ((this._tokenModel.expires - elapsedSeconds) > 1 * 3600) {
      // 剩余时间大于2小时不刷新
      return;
    }
    api.refreshToken(this._tokenModel?.token).then((tokenModel) => {
      this._save({ tokenModel });
      this._load();
    }).catch((e) => {
      console.error(e);
    });
  }

  _load() {
    let pdata = persist.getObject('token');
    if (!pdata) { // try load from cookie
      const token = globalThis.Cookie.get('token');
      if (token) {
        pdata = { token, expires: 0 };
      }
    }
    if (pdata) {
      const { tokenModel, payload, username } = parseToken(pdata);
      this._tokenModel = tokenModel;
      this.tokenPayload = payload;
      this.lastUsername = username;

      // 填写全局变量
      global.TENANT = username?.substr(username?.lastIndexOf('@') + 1);
      global.TOKEN = this._tokenModel?.token;
      global.ENV = this.tokenPayload.env;
    }
    this.lastUsername = persist.getItem('lastUsername', '');
    this.me = persist.getObject('me') || {};
    this.endpoints = persist.getObject('endpoints') || [];
    // 填写全局变量
    global.me = this.me;
    global.isAdmin = this.me?.username.split('@')[0] === 'admin';
    // console.log('=======', global.isAdmin);
    // setTimeout(async () => {
    //   await this.currentAdmin();
    // }, 0);
    if (this._tokenModel?.token) {
      // 广播token就绪事件
      setTimeout(async () => {
        // 每次启动时检查是否需要刷新token
        this._refreshTokenIfNeeded();
        await this._fetchMe(); // 发起更新
        Events.emit(EVENT.TOKEN_READY);
        Events.emit(EVENT.USER_READY);
      }, 0);
    }
  }

  _save({ tokenModel, me }) {
    persist.setObject('token', tokenModel);
    if (me) {
      persist.setItem('lastUsername', me.username);
      persist.setObject('me', me);
    }
    persist.setObject('endpoints', toJS(this.endpoints));
  }

  async _fetchMe() {
    const me = await api.me();
    const endpoints = await api.getEndpoints();
    this.endpoints = endpoints;
    Object.assign(this.me, me);
    global.me = this.me;
    persist.setItem('lastUsername', me.username);
    persist.setObject('me', me);
    persist.setObject('endpoints', endpoints);
  }

  /**
   * 发起认证
   * 1. 请求认证
   * 2. 缓存返回token到localStorage
   * 3. 请求me，并缓存到localStorage
   * 4. 调用_load加载缓存并设置全局变量，广播事件等
   */
  async auth(authModel) {
    const tokenModel = await api.auth(authModel);
    await this._handleTokenModel(tokenModel);
  }

  // 手机号登陆
  async authSms(authModel) {
    const tokenModel = await api.authSms(authModel);
    await this._handleTokenModel(tokenModel);
  }

  async _handleTokenModel(tokenModel) {
    global.TOKEN = tokenModel?.token; // 仅供下面请求使用
    await this._fetchMe();
    this._save({ tokenModel, me: this.me });
    this._load();
  }

  /**
   * 注销登录
   */
  logout() {
    persist.removeItem('token');
    persist.removeAllItem();
    this._tokenModel = null;
    global.TOKEN = undefined;
    global.me = undefined;
    RSocket?.close();
    window.location.reload();
    return Promise.resolve();
  }

  _expired() {
    const currentTimestamp = new Date().getTime() / 1000;
    const elapsedSeconds = (currentTimestamp - this.tokenPayload.iat);
    const expired = elapsedSeconds - this._tokenModel.expires > 600;
    if (expired) {
      this.logout();
    }
    return expired;
  }

  get authed() {
    return this._tokenModel?.token?.length > 0 && !this._expired();
  }

  get fullname() {
    return this.me.fullname == this.me.accountId ? '' : this.me.fullname;
  }

  get env() {
    return this.tokenPayload?.env || 'sit';
  }

  async getCode() {
    return await api.getCode();
  }
}
